package org.apache.jmeter.assertions;

import java.io.Serializable;

import org.apache.jmeter.samplers.SampleResult;
import org.apache.jmeter.testelement.AbstractTestElement;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
import org.apache.oro.text.regex.Pattern;
import org.apache.jmeter.util.JMeterUtils;
import net.minidev.json.JSONArray;
import com.jayway.jsonpath.internal.JsonReader;



public class JSONAssertion extends AbstractTestElement implements Assertion, TestElement, Serializable {

	private static final long serialVersionUID = 240L;
	
	private static final Logger log = LoggingManager.getLoggerForClass();
	
	private static String jsonPath = "JSONPATH";
	private static String expectedData = "EXPECTEDDATA";
	private static String isCheck = "isCheck";
	private static String formatString = "\n\tExpected:%s  \n\tResult:%s";
	
	public JSONAssertion() {
		super();
		log.debug("JSONAssertion(): called");
	}
	
	 
	
	@Override
	public AssertionResult getResult(SampleResult response){
		log.debug("getResult(): called");
		AssertionResult result = new AssertionResult(getName());
		
		if (response.getResponseData().length == 0) {
            return result.setResultForNull();
        }
		
		String responseString = response.getResponseDataAsString();
		result.setFailure(false);
		result.setFailureMessage("");
		
		JsonReader reader = new JsonReader();
		try{
			reader.parse(responseString);
			
		}catch (Exception e){
			result.setFailure(false);
			result.setFailureMessage(e.getMessage());
		}
		Object value = reader.read(getJsonpath());
		if(Ischeck()){
			try{
				if (value instanceof JSONArray){
					JSONArray arr = (JSONArray)value;
					if(arr.isEmpty() && getExpecteddata().equals("[]")){
						return result;
					}
					Boolean tempResult = false;
					for (Object temp : arr.toArray()){
						if(isEquals(temp.toString())){
							tempResult = true;
						}
					}
					
					if(!tempResult){
						result.setFailure(true);
						result.setFailureMessage(String.format(formatString, getExpecteddata(),value.toString()));
					}
				}else{
					if(!isEquals(value.toString())){
						result.setFailure(true);
						result.setFailureMessage(String.format(formatString, getExpecteddata(),value.toString()));
					}
				}
			}catch (Exception e){
				result.setFailure(true);
				result.setFailureMessage(e.getMessage());
			}
		}
		return result;
	}

	private boolean isEquals(String subj) {
        Pattern pattern = JMeterUtils.getPatternCache().getPattern(getExpecteddata());
        return JMeterUtils.getMatcher().matches(subj, pattern);
    }

	public String getJsonpath() {
		return getPropertyAsString(jsonPath);
	}



	public void setJsonpath(String value) {
		setProperty(jsonPath,value);
	}



	public String getExpecteddata() {
		return getPropertyAsString(expectedData);
	}



	public void setExpecteddata(String value) {
		setProperty(expectedData,value);
	}



	public Boolean Ischeck() {
		return getPropertyAsBoolean(isCheck);
	}



	public void setIscheck(Boolean value) {
		setProperty(isCheck,value);
	}
	
}
